Fix NATS JetStream native scheduled send (err 10190) and add configurable schedule-subject suffix.#3017
Merged
Conversation
…able schedule-subject suffix.
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Fixes NATS JetStream native scheduled-send failures (err 10190) by publishing the scheduling “control” message to a derived subject (target + suffix) while keeping Nats-Schedule-Target as the true destination.
Changes:
- Add configurable schedule-subject suffix on
NatsEndpointand plumb it intoJetStreamPublisher - Adjust JetStream scheduled publish logic to use a derived schedule subject
- Add tests and documentation describing the err 10190 behavior and the stream subject coverage requirements
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Transports/NATS/Wolverine.Nats/Internal/NatsSender.cs | Pass per-endpoint schedule suffix into JetStreamPublisher |
| src/Transports/NATS/Wolverine.Nats/Internal/NatsEndpoint.cs | Introduce ScheduleSubjectSuffix setting with docs |
| src/Transports/NATS/Wolverine.Nats/Internal/JetStreamPublisher.cs | Publish scheduled control messages to subject + suffix to avoid err 10190 |
| src/Transports/NATS/Wolverine.Nats/Configuration/NatsSubscriberConfiguration.cs | Add fluent configuration for schedule suffix |
| src/Transports/NATS/Wolverine.Nats.Tests/ScheduledMessageDeliveryTests.cs | Integration test reproducing/guarding against err 10190 |
| src/Transports/NATS/Wolverine.Nats.Tests/NatsScheduleSubjectSuffixTests.cs | Unit tests for default + configuration round-trip |
| docs/guide/messaging/transports/nats.md | Document scheduling subject derivation and stream wildcard requirements |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Member
|
@midub I'll try to get this reviewed and in today |
Member
|
@midub Looks good to me, I'll be getting this in today. I think that will be 6.4.2, but might be 6.5. Depends on what else comes in in the meantime. |
This was referenced Jun 8, 2026
Merged
This was referenced Jun 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Wolverine.Natsfails to send any scheduled message over NATS JetStream native scheduling (NATS Server 2.12+). The transport publishes the scheduling control message to the same subject it sets as theNats-Schedule-Targetheader, but NATS requires the control message to be published to a subject different from the target. The server rejects the publish:{"error":{"code":400,"err_code":10190,"description":"message schedules target is invalid"}}The send throws, nothing is materialized, and the consumer never receives the message.
Fix
JetStreamPublishernow keepsNats-Schedule-Target= the real destination subject (where the listener's exact-FilterSubjectconsumer reads and the server materializes the message at fire time) and publishes the control message to a derived subject:<subject>.scheduled.UseScheduleSubjectSuffix(...).prefix.>filter (a single-token*/ exact-subject filter will not cover the derived subject)..scheduled, so the control subject can never collapse onto the target again.Tests
schedule_send_over_native_jetstream_scheduling— drives the native path by putting.UseJetStream(stream)on the publishing endpoint. Times out before the fix, passes after. Asserts the native path is engaged (not the durable fallback). Skips on NATS < 2.12.overridden_suffix_is_used_for_native_scheduling— provisions the stream with explicit subjects covering only the target and the.override-scheduledsubject (default.scheduleddeliberately not covered), so delivery only succeeds if the configured suffix is actually applied.